package com.flashextended.apps.logomaker.model
{
	import com.adobe.images.JPGEncoder;
	import com.adobe.images.PNGEncoder;
	import com.adobe.serialization.json.JSON;
	import com.flashextended.apps.logomaker.beans.workareaobjects.GenericObject;
	import com.flashextended.apps.logomaker.beans.workareaobjects.ImageOnStage;
	import com.flashextended.apps.logomaker.beans.workareaobjects.SymbolOnStage;
	import com.flashextended.apps.logomaker.beans.workareaobjects.TextOnStage;
	import com.flashextended.apps.logomaker.singleton.AppControl;
	import com.flashextended.apps.logomaker.singleton.AppLocales;
	import com.flashextended.utils.server.filereference.FileReferenceLocale;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.events.Event;
	import flash.net.FileFilter;
	import flash.net.URLLoader;
	import flash.utils.ByteArray;
	import flash.utils.IDataInput;
	
	import mx.collections.ArrayCollection;
	import mx.controls.Alert;
	
	import nochump.util.zip.ZipEntry;
	import nochump.util.zip.ZipFile;
	import nochump.util.zip.ZipOutput;
	


	public class Model
	{
		public function Model()
		{
		}
		
		/**
		 * singleton impl
		 */ 
		private static var instance:Model;
		public static function getInstance():Model
		{
			if(instance==null)
			{
				instance = new Model();
			}
			return instance;
		}
		
		/**
		 * start save project
		 */ 
		public function saveProject():void
		{
			var uiObjects:ArrayCollection = AppControl.getInstance().workarea.getGraphicObjects();
			if(uiObjects.length==0)
			{
				Alert.show( AppLocales.getInstance().data.locales["errorSaveProject"], "Error!");
				return;
			}
			//continue
			var jsonObjects:Array = new Array();
			var imagesAC:ArrayCollection = new ArrayCollection();
			
			for(var i:int=0;i<uiObjects.length;i++)
			{
				var objectUI:GenericObject = GenericObject(uiObjects.getItemAt(i));
				var jsonObject:Object = new Object();
				jsonObject.objectX = objectUI.x;
				jsonObject.objectY = objectUI.y;
				jsonObject.objectWidth = objectUI.width;
				jsonObject.objectHeight = objectUI.height;
				jsonObject.type = objectUI.type;
				jsonObject.objectRotation = objectUI.rotation;

				if(jsonObject.type=="IMAGE")
				{
					jsonObject.idImage = ImageOnStage(objectUI).idImage;
					jsonObject.brightness = ImageOnStage(objectUI).brightness;
					jsonObject.contrast = ImageOnStage(objectUI).contrast;
					jsonObject.saturation = ImageOnStage(objectUI).saturation;
					
					var imageBytes:ByteArray = PNGEncoder.encode(ImageOnStage(objectUI).originalBitmap.bitmapData);
					var rowImage:Object = new Object();
					rowImage.bytes = imageBytes;
					rowImage.idImage = jsonObject.idImage;
					imagesAC.addItem(rowImage);
				}
				if(jsonObject.type=="TEXT")
				{
					jsonObject.fontType = TextOnStage(objectUI).fontType;
					jsonObject.fontColor = TextOnStage(objectUI).fontColor;
					jsonObject.fontSize = TextOnStage(objectUI).fontSize;
					jsonObject.fontAlign = TextOnStage(objectUI).fontAlign;
					jsonObject.fontBold = TextOnStage(objectUI).fontBold;
					jsonObject.fontItalic = TextOnStage(objectUI).fontItalic;
					jsonObject.fontUnderline = TextOnStage(objectUI).fontUnderline;
					jsonObject.textFeed = TextOnStage(objectUI).getTextFeed();
				}
				if(jsonObject.type=="SYMBOL")
				{
					jsonObject.idImage = SymbolOnStage(objectUI).idImage;
					jsonObject.symbolColor = SymbolOnStage(objectUI).symbolColor;
					var symbolImageBytes:ByteArray = PNGEncoder.encode(SymbolOnStage(objectUI).loaderContent.bitmapData);
					var symbolRowImage:Object = new Object();
					symbolRowImage.bytes = symbolImageBytes;
					symbolRowImage.idImage = jsonObject.idImage;
					imagesAC.addItem(symbolRowImage);					
				}
				jsonObjects.push(jsonObject);
			}
			
			var encodedObj:Object = com.adobe.serialization.json.JSON.encode(jsonObjects);
			
			var fileName:String = "objects.txt";
			var fileData:ByteArray = new ByteArray();
			fileData.writeUTFBytes(encodedObj.toString());			
			
			var zipOut:ZipOutput = new ZipOutput();
			var ze:ZipEntry = new ZipEntry(fileName);
			zipOut.putNextEntry(ze);
			zipOut.write(fileData);
			zipOut.closeEntry();
			
			for(var j:int=0;j<imagesAC.length;j++)
			{
				var fileData2:ByteArray = ByteArray(imagesAC.getItemAt(j).bytes);				
				var ze2:ZipEntry = new ZipEntry(imagesAC.getItemAt(j).idImage);
				zipOut.putNextEntry(ze2);
				zipOut.write(fileData2);
				zipOut.closeEntry();				
			}
			
			zipOut.finish();
			
			// access the zip data
			var zipData:ByteArray = zipOut.byteArray;		
			var fRef:FileReferenceLocale = new FileReferenceLocale();
			fRef.saveFile(zipData, "logoProject.lgp");			
		}
		
		/**
		 * load project
		 */ 
		public function loadProject():void
		{
			//TBD - clear stage / infor user
			var fRef:FileReferenceLocale = new FileReferenceLocale(new FileFilter("Logo Maker Project", "*.*"));
			fRef.browseForDataLocally(projectLoaded, true);
		}
		
		/**
		 * project loaded
		 */ 
		private var loader:Loader;
		private var loadedZipFile:ZipFile;
		private var countZipElements:int;
		private var zipImagesAC:ArrayCollection;
		
		private function projectLoaded(bytes:ByteArray):void
		{
			countZipElements = -1;
			var loadedData:ByteArray = bytes;
			try
			{
				loadedZipFile = new ZipFile(loadedData);
			}catch(e:Error)
			{
				Alert.show('Corupted file!', 'Error!');
			}
			zipImagesAC = new ArrayCollection();
			extractZipElement();			
		}
		
		private var decodedObjects:Object;
		private var currentImageID:String;
		
		/**
		 * extract zip archive
		 */ 
		private function extractZipElement():void
		{
			countZipElements++;
			if(countZipElements<loadedZipFile.entries.length)
			{
				//extract
				var entry:ZipEntry = loadedZipFile.entries[countZipElements];
				var data:ByteArray = loadedZipFile.getInput(entry);
				if(entry.name == "objects.txt")
				{
					//decode JSON
					decodedObjects = com.adobe.serialization.json.JSON.decode(data.toString());
					extractZipElement();
				}
				else
				{
					//extract image
					currentImageID = entry.name;
					loader = new Loader();
					loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderCompletedLoad);
					loader.loadBytes(data);					
				}
			}
			else
			{
				//finish extract
				//start display
				displayProject();
			}
		}
		
		/**
		 * add objects to workarea
		 */ 
		private function displayProject():void
		{
			var uiObjects:Array = decodedObjects as Array;
			//trace(uiObjects[0].toString());
			for(var i:int=0;i<uiObjects.length;i++)
			{
				var genericObject:GenericObject;
				if(uiObjects[i].type=="IMAGE")
				{				
					
					//build image
					genericObject = new ImageOnStage(extractImage(uiObjects[i].idImage));
					
					ImageOnStage(genericObject).brightness = uiObjects[i].brightness;
					ImageOnStage(genericObject).contrast = uiObjects[i].contrast;
					ImageOnStage(genericObject).saturation = uiObjects[i].saturation;					
					
				}
				if(uiObjects[i].type=="TEXT")
				{
					//build text
					genericObject = new TextOnStage(uiObjects[i].textFeed);
					
					TextOnStage(genericObject).fontType = uiObjects[i].fontType;
					TextOnStage(genericObject).fontColor = uiObjects[i].fontColor;
					TextOnStage(genericObject).fontSize = uiObjects[i].fontSize;
					TextOnStage(genericObject).fontAlign = uiObjects[i].fontAlign;
					TextOnStage(genericObject).fontBold = uiObjects[i].fontBold;
					TextOnStage(genericObject).fontItalic = uiObjects[i].fontItalic;
					TextOnStage(genericObject).fontUnderline = uiObjects[i].fontUnderline;
									
				}
				if(uiObjects[i].type=="SYMBOL")
				{
					//build symbol
					genericObject = new SymbolOnStage(extractImage(uiObjects[i].idImage));
					SymbolOnStage(genericObject).symbolColor = uiObjects[i].symbolColor;
				}
				genericObject.width = uiObjects[i].objectWidth;
				genericObject.height = uiObjects[i].objectHeight;
				genericObject.x = uiObjects[i].objectX;
				genericObject.y = uiObjects[i].objectY;
				genericObject.rotation = uiObjects[i].objectRotation;
				genericObject.objectRotation = uiObjects[i].objectRotation;
				
				AppControl.getInstance().workarea.addExtractedObject(genericObject);
				AppControl.getInstance().workarea.unselectObjects();
			}
		}
		
		/**
		 * image from zip loaded
		 */ 
		private function loaderCompletedLoad(e:Event):void
		{
			var bmd:BitmapData = new BitmapData(loader.width, loader.height, true, 1);
			bmd.draw(loader.content);
			var bmp:Bitmap = new Bitmap(bmd);
			
			var imageObj:Object = new Object();
			imageObj.imageId = currentImageID;
			imageObj.image = bmp;
			zipImagesAC.addItem(imageObj);
			
			extractZipElement();
			/*
			var imageOnStage:ImageOnStage = new ImageOnStage(bmp);
			imageOnStage.width = 107;
			imageOnStage.height = 92;
			AppControl.getInstance().workarea.addObject(imageOnStage);
			*/
		}
		
		private function extractImage(imageID:String):Bitmap
		{
			var bmp:Bitmap;
			for(var i:int=0;i<zipImagesAC.length;i++)
			{
				if(imageID==zipImagesAC.getItemAt(i).imageId)
				{
					bmp = zipImagesAC.getItemAt(i).image;
					break;
				}
			}
			return bmp;
		}
		
	}
}